// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// Test that rnd.nextInt with a seed generates the same sequence each time.

// Library tag to allow Dartium to run the test.
library random_test;

import "package:expect/expect.dart";
import 'dart:math';

main() {
  checkSequence();
  checkSeed();
}

void checkSequence() {
  // Check the sequence of numbers generated by the random generator for a seed
  // doesn't change unintendedly, and it agrees between implementations.
  var rnd = new Random(20130307);
  // Make sure we do not break the random number generation.
  // If the random algorithm changes, make sure both the VM and dart2js
  // generate the same new sequence.
  var i = 1;
  Expect.equals(         0, rnd.nextInt(i *= 2));
  Expect.equals(         3, rnd.nextInt(i *= 2));
  Expect.equals(         7, rnd.nextInt(i *= 2));
  Expect.equals(         5, rnd.nextInt(i *= 2));
  Expect.equals(        29, rnd.nextInt(i *= 2));
  Expect.equals(        17, rnd.nextInt(i *= 2));
  Expect.equals(       104, rnd.nextInt(i *= 2));
  Expect.equals(       199, rnd.nextInt(i *= 2));
  Expect.equals(       408, rnd.nextInt(i *= 2));
  Expect.equals(       362, rnd.nextInt(i *= 2));
  Expect.equals(       995, rnd.nextInt(i *= 2));
  Expect.equals(      2561, rnd.nextInt(i *= 2));
  Expect.equals(      2548, rnd.nextInt(i *= 2));
  Expect.equals(      9553, rnd.nextInt(i *= 2));
  Expect.equals(      2628, rnd.nextInt(i *= 2));
  Expect.equals(     42376, rnd.nextInt(i *= 2));
  Expect.equals(    101848, rnd.nextInt(i *= 2));
  Expect.equals(     85153, rnd.nextInt(i *= 2));
  Expect.equals(    495595, rnd.nextInt(i *= 2));
  Expect.equals(    647122, rnd.nextInt(i *= 2));
  Expect.equals(    793546, rnd.nextInt(i *= 2));
  Expect.equals(   1073343, rnd.nextInt(i *= 2));
  Expect.equals(   4479969, rnd.nextInt(i *= 2));
  Expect.equals(   9680425, rnd.nextInt(i *= 2));
  Expect.equals(  28460171, rnd.nextInt(i *= 2));
  Expect.equals(  49481738, rnd.nextInt(i *= 2));
  Expect.equals(   9878974, rnd.nextInt(i *= 2));
  Expect.equals( 132552472, rnd.nextInt(i *= 2));
  Expect.equals( 210267283, rnd.nextInt(i *= 2));
  Expect.equals( 125422442, rnd.nextInt(i *= 2));
  Expect.equals( 226275094, rnd.nextInt(i *= 2));
  Expect.equals(1639629168, rnd.nextInt(i *= 2));
  Expect.equals(0x100000000, i);
  // If max is too large expect an ArgumentError.
  Expect.throws(() => rnd.nextInt(i + 1), (e) => e is ArgumentError);

  rnd = new Random(6790);
  Expect.approxEquals(0.1202733131, rnd.nextDouble());
  Expect.approxEquals(0.5554054805, rnd.nextDouble());
  Expect.approxEquals(0.0385160727, rnd.nextDouble());
  Expect.approxEquals(0.2836345217, rnd.nextDouble());
}

void checkSeed() {
  // Check that various seeds generate the expected first values.
  // 53 significant bits, so the number is representable in JS.
  var rawSeed = 0x19a32c640e1d71;
  var expectations = [
    26007, 43006, 46458, 18610, 16413, 50455,  2164, 47399,  8859,  9732,
    20367, 33935, 54549, 54913,  4819, 24198, 49353, 22277, 51852, 35959,
    45347, 12100, 10136, 22372, 15293, 20066,  1351, 49030, 64845, 12793,
    50916, 55784, 43170, 27653, 34696,  1492, 50255,  9597, 45929,  2874,
    27629, 53084, 36064, 42140, 32016, 41751, 13967, 20516,   578, 16773,
    53064, 14814, 22737, 48846, 45147, 10205, 56584, 63711, 44128, 21099,
    47966, 35471, 39576,  1141, 45716, 54940, 57406, 15437, 31721, 35044,
    28136, 39797, 50801, 22184, 58686
  ];
  var negative_seed_expectations = [
    12170, 42844, 39228, 64032, 29046, 57572,  8453, 52224, 27060, 28454,
    20510, 28804, 59221, 53422, 11047, 50864, 33997, 19611,  1250, 65088,
    19690, 11396,    20, 48867, 44862, 47129, 58724, 13325, 50005, 33320,
    16523,  4740, 63721, 63272, 30545, 51403, 35845,  3943, 31850, 23148,
    26307,  1724, 29281, 39988, 43653, 48012, 43810, 16755, 13105, 25325,
    32648, 19958, 38838,  8322,  3421, 28624, 17269, 45385, 50680,  1696,
    26088,  2787, 48566, 34357, 27731, 51764,  8455, 16498, 59721, 59568,
    46333,  7935, 51459, 36766, 50711
  ];
  for (var i = 0, m = 1; i < 75; i++) {
    Expect.equals(expectations[i], new Random(rawSeed * m).nextInt(65536));
    Expect.equals(negative_seed_expectations[i],
                  new Random(rawSeed * -m).nextInt(65536));
    m *= 2;
  }
  // And test zero seed too.
  Expect.equals(21391, new Random(0).nextInt(65536));
}
